#ifndef __NAVMESH_UTILS_H_
#define __NAVMESH_UTILS_H_
#include "DetourTileCache.h"
#include "DetourTileCacheBuilder.h"
#include <math.h>

/// These are just sample areas to use consistent values across the samples.
/// The use should specify these base on his needs.
enum SamplePolyAreas
{
	SAMPLE_POLYAREA_GROUND,
	SAMPLE_POLYAREA_WATER,
	SAMPLE_POLYAREA_ROAD,
	SAMPLE_POLYAREA_DOOR,
	SAMPLE_POLYAREA_GRASS,
	SAMPLE_POLYAREA_JUMP,
};
enum SamplePolyFlags
{
	SAMPLE_POLYFLAGS_WALK = 0x01,		// Ability to walk (ground, grass, road)
	SAMPLE_POLYFLAGS_SWIM = 0x02,		// Ability to swim (water).
	SAMPLE_POLYFLAGS_DOOR = 0x04,		// Ability to move through doors.
	SAMPLE_POLYFLAGS_JUMP = 0x08,		// Ability to jump.
	SAMPLE_POLYFLAGS_DISABLED = 0x10,		// Disabled polygon
	SAMPLE_POLYFLAGS_ALL = 0xffff	// All abilities.
};

struct LinearAllocator : public dtTileCacheAlloc
{
	unsigned char* buffer;
	int capacity;
	int top;
	int high;

	LinearAllocator(const int cap);

	~LinearAllocator();

	void resize(const int cap);

	virtual void reset();

	virtual void* alloc(const int size);

	virtual void free(void* /*ptr*/);
};


struct FastLZCompressor : public dtTileCacheCompressor
{
	virtual int maxCompressedSize(const int bufferSize);

	virtual dtStatus compress(const unsigned char* buffer, const int bufferSize,
		unsigned char* compressed, const int /*maxCompressedSize*/, int* compressedSize);

	virtual dtStatus decompress(const unsigned char* compressed, const int compressedSize,
		unsigned char* buffer, const int maxBufferSize, int* bufferSize);
};

struct GeomData
{
	static const int MAX_OFFMESH_CONNECTIONS = 256;
	float offMeshConVerts[MAX_OFFMESH_CONNECTIONS * 3 * 2];
	float offMeshConRads[MAX_OFFMESH_CONNECTIONS];
	unsigned char offMeshConDirs[MAX_OFFMESH_CONNECTIONS];
	unsigned char offMeshConAreas[MAX_OFFMESH_CONNECTIONS];
	unsigned short offMeshConFlags[MAX_OFFMESH_CONNECTIONS];
	unsigned int offMeshConId[MAX_OFFMESH_CONNECTIONS];
	int offMeshConCount;
};

struct MeshProcess : public dtTileCacheMeshProcess
{
	const GeomData *data;

	MeshProcess();
	virtual ~MeshProcess();

	void init(const GeomData *geom)
	{
		data = geom;
	}

	virtual void process(struct dtNavMeshCreateParams* params,
		unsigned char* polyAreas, unsigned short* polyFlags) override;
};

bool inRange(const float* v1, const float* v2, const float r, const float h);
#endif